<?php
/**
 * Desc:
 * User: zdb
 * Date: 2022/10/8
 * Time: 16:48
 */

namespace app\util;

use app\admin\util\cache\UserLoginInfoRedisCacheUtil;
use com\nlf\calendar\Solar;
use com\nlf\calendar\util\HolidayUtil;
use DateTime;

class DateUtil {
    public static function getCustomDatetime($date, $format = "Y-m-d H:i:s") {
        if (is_numeric($date)) {
            return date($format, $date);
        } else {
            return date($format, strtotime($date));
        }
    }

    public static function getCurrentDatetime($format = "Y-m-d H:i:s") {
        return date($format);
    }

    public static function getCurrentTimeBySection($format = 'Y-m-d H:i:s', $site = 0) {
        if (!$site) {
            $site = UserLoginInfoRedisCacheUtil::getRedisCacheSection()['data'];
        }
        $timezone = date('e');  //获取当前使用的时区
        if ($site) {
            switch ($site) {
                case '3'://North America
                    date_default_timezone_set('America/Detroit'); //设置时区为底特律
                    break;
                case '4'://Europe
                    date_default_timezone_set('Europe/Prague'); //设置时区为柏林
                    break;
                default:
                    break;
            }
        }
        $time = date($format);
        date_default_timezone_set($timezone);  //还原时区
        return $time;
    }


    /**
     * Desc: 获取时间轴横坐标显示
     * @param $timeGranularity second\minute\hour\day\month\year
     * @param $time  start_time、end_time, 起始及结束时间
     * @param int $dataNum  如果dataNum有数值，优先按dataNum进行
     * @return array
     * Datetime: 2023/2/9 14:01 by zdb
     */
    public static function getChartXDate($timeGranularity, $time, $dataNum = 0) {
        $newArr = [];
        $startTimeInt = empty($time['start_time']) ? strtotime(self::getCurrentDatetime()) : strtotime($time['start_time']);
        $endTime = empty($time['end_time']) ? self::getCurrentDatetime() : $time['end_time'];
        $endTimeInt = empty($time['end_time']) ? strtotime(self::getCurrentDatetime()) : strtotime($time['end_time']);
        $count = 0;  //月份有点特殊，不能按固定一个月30天来算
        $num = 0;  //默认最多显示50条数据
        if ($dataNum > 0) {
            while ($num < $dataNum + 1) {
                if ('second' == $timeGranularity) {
                    $endTimeInt = $endTimeInt - 1;
                    $newArr[] = date("Y-m-d H:i:s", $endTimeInt);
                } else if ('minute' == $timeGranularity) {
                    $endTimeInt = $endTimeInt - 60;
                    $newArr[] = date("Y-m-d H:i", $endTimeInt);
                } else if ('hour' == $timeGranularity) {
                    $endTimeInt = $endTimeInt - 3600;
                    $newArr[] = date("Y-m-d H:00", $endTimeInt);
                } else if ('day' == $timeGranularity) {
                    $endTimeInt = $endTimeInt - 86400;
                    $newArr[] = date("Y-m-d", $endTimeInt);
                } else if ('month' == $timeGranularity) {
                    $count++;
                    $endTimeInt = strtotime(date("Y-m-01", strtotime($endTime . "-" . $count . " months")));
                    $newArr[] = date("Y-m", $endTimeInt);
                } else if ('year' == $timeGranularity) {
                    $count++;
                    $endTimeInt = strtotime(date("Y-m", strtotime($endTime . "-" . $count . " years")));
                    $newArr[] = date("Y", $endTimeInt);
                }
                $num++;
            }
        } else {
            if ('second' == $timeGranularity) {
                $newArr[] = date("Y-m-d H:i:s", $endTimeInt);
            } else if ('minute' == $timeGranularity) {
                $newArr[] = date("Y-m-d H:i", $endTimeInt);
            } else if ('hour' == $timeGranularity) {
                $newArr[] = date("Y-m-d H:00", $endTimeInt);
            } else if ('day' == $timeGranularity) {
                $newArr[] = date("Y-m-d", $endTimeInt);
            } else if ('month' == $timeGranularity) {
                $endTimeInt = strtotime(date("Y-m-01", strtotime($endTime . "-" . $count . " months")));
                $newArr[] = date("Y-m", $endTimeInt);
            } else if ('year' == $timeGranularity) {
                $endTimeInt = strtotime(date("Y-m", strtotime($endTime . "-" . $count . " years")));
                $newArr[] = date("Y", $endTimeInt);
            }
            while ($endTimeInt > $startTimeInt) {
                if ('second' == $timeGranularity) {
                    $endTimeInt = $endTimeInt - 1;
                    $newArr[] = date("Y-m-d H:i:s", $endTimeInt);
                } else if ('minute' == $timeGranularity) {
                    $endTimeInt = $endTimeInt - 60;
                    $newArr[] = date("Y-m-d H:i", $endTimeInt);
                } else if ('hour' == $timeGranularity) {
                    $endTimeInt = $endTimeInt - 3600;
                    $newArr[] = date("Y-m-d H:00", $endTimeInt);
                } else if ('day' == $timeGranularity) {
                    $endTimeInt = $endTimeInt - 86400;
                    $newArr[] = date("Y-m-d", $endTimeInt);
                } else if ('month' == $timeGranularity) {
                    $count++;
                    $endTimeInt = strtotime(date("Y-m-01", strtotime($endTime . "-" . $count . " months")));
                    $newArr[] = date("Y-m", $endTimeInt);
                } else if ('year' == $timeGranularity) {
                    $count++;
                    $endTimeInt = strtotime(date("Y-m", strtotime($endTime . "-" . $count . " years")));
                    $newArr[] = date("Y", $endTimeInt);
                }
            }
        }
        return array_reverse($newArr);
    }

    /**
     * Desc: 折线图横坐标显示的文本处理
     * 每个阶段的第一个时间，多点内容。例如11月01号，显示11-01
     * 时间段的起点，多点内容，例如七点是12号的08小时，显示12 08
     * 时间段的结束点，多点内容
     * @param $timeGranularity
     * @param $startTime
     * @param $endTime
     * @param $dataNum
     * Datetime: 2022/11/25 17:25 by zdb
     */
    public static function getChartXDateTitle($timeGranularity, $dateArr) {
        $newArr = [];
        $setting = array(
            'second' => array(
                'format' => 's',
                'format_special' => 'i:s'
            ),
            'minute' => array(
                'format' => 'i',
                'format_special' => 'H:i'
            ),
            'hour' => array(
                'format' => 'H',
                'format_special' => 'd H'
            ),
            'day' => array(
                'format' => 'j',
                'format_special' => 'm-j'
            ),
            'month' => array(
                'format' => 'n',
                'format_special' => 'Y-n'
            ),
            'year' => array(
                'format' => 'Y',
                'format_special' => 'Y'
            ),
        );
        $arrCount = count($dateArr);
        $timeGranularity = strtolower($timeGranularity);
        foreach ($dateArr as $key => $date) {
            $criticalPoint = date($setting[$timeGranularity]['format'], strtotime($date));
            if (0 == $key || $arrCount - 1 == $key || 1 == intval($criticalPoint)) {
                $newArr[] = date($setting[$timeGranularity]['format_special'], strtotime($date));
            } else {
                $newArr[] = date($setting[$timeGranularity]['format'], strtotime($date));
            }
        }
        return $newArr;
    }

    public static function getChartXDateTitleLong($timeGranularity, $dateArr) {
        $newArr = [];
        $setting = array(
            'second' => array(
                'format' => 'Y-m-d H:i:s',
            ),
            'minute' => array(
                'format' => 'Y-m-d H:i:00',
            ),
            'hour' => array(
                'format' => 'Y-m-d H:00',
            ),
            'day' => array(
                'format' => 'Y-m-d',
            ),
            'month' => array(
                'format' => 'Y-m',
            ),
            'year' => array(
                'format' => 'Y',
            ),
        );
        $timeGranularity = strtolower($timeGranularity);
        foreach ($dateArr as $key => $date) {
            $newArr[] = date($setting[$timeGranularity]['format'], strtotime($date));
        }
        return $newArr;
    }

    public static function getLastMonthStartEndTime() {
        $nowStartTime = self::getCurrentDatetime("Y-m-01 00:00:00");
        $startTime = self::getCustomDatetime($nowStartTime . "-1 month");
        $endTime = self::getCustomDatetime($nowStartTime . "-1 days", "Y-m-d 23:59:59");
        return array('start_time' => $startTime, 'end_time' => $endTime);
    }

    public static function getYesterdayStartEndTime() {
        $nowStartTime = self::getCurrentDatetime("Y-m-d 00:00:00");
        $startTime = self::getCustomDatetime($nowStartTime . "-1 days");
        $endTime = self::getCustomDatetime($nowStartTime . "-1 days", "Y-m-d 23:59:59");
        return array('start_time' => $startTime, 'end_time' => $endTime);
    }

    public static function getLastHourStartEndTime() {
        $nowStartTime = self::getCurrentDatetime("Y-m-d H:00:00");
        $startTime = self::getCustomDatetime($nowStartTime . "-1 hours");
        $endTime = self::getCustomDatetime($nowStartTime . "-1 hours", "Y-m-d H:59:59");
        return array('start_time' => $startTime, 'end_time' => $endTime);
    }

    /**
     * Desc: 获取某一个时间段最近多少天/小时等的开始时间和结束时间
     * @param $timeGranularity
     * @param $startTime
     * @param $endTime
     * @param $dataNum
     * @return array
     * Datetime: 2022/12/2 17:04 by zdb
     */
    public static function getPeriodStartAndEndTime($timeGranularity, $startTime, $endTime, $dataNum) {
        $newArr = [];
        $startTimeInt = strtotime($startTime);
        $endTimeInt = strtotime($endTime);
        $count = 0;  //月份有点特殊，不能按固定一个月30天来算
        $num = 0;  //默认最多显示50条数据
        while ($endTimeInt > $startTimeInt && $num < $dataNum + 1) {
            if ('second' == $timeGranularity) {
                $endTimeInt = $endTimeInt - 1;
                $periodStartTime = date("Y-m-d H:i:s", $endTimeInt);
                $newArr[] = [
                    'start_time' => $periodStartTime,
                    'end_time' => $periodStartTime,
                ];
            } else if ('minute' == $timeGranularity) {
                $endTimeInt = $endTimeInt - 60;
                $newArr[] = [
                    'start_time' => date("Y-m-d H:i:00", $endTimeInt),
                    'end_time' => date("Y-m-d H:i:59", $endTimeInt),
                ];
                $newArr[] = date("Y-m-d H:i", $endTimeInt);
            } else if ('hour' == $timeGranularity) {
                $endTimeInt = $endTimeInt - 3600;
                $newArr[] = [
                    'start_time' => date("Y-m-d H:00:00", $endTimeInt),
                    'end_time' => date("Y-m-d H:59:59", $endTimeInt),
                ];
            } else if ('day' == $timeGranularity) {
                $endTimeInt = $endTimeInt - 86400;
                $newArr[] = [
                    'start_time' => date("Y-m-d 00:00:00", $endTimeInt),
                    'end_time' => date("Y-m-d 23:59:59", $endTimeInt),
                ];
            } else if ('month' == $timeGranularity) {
                $count++;
                $firstDay = date("Y-m-01", strtotime($endTime . "-" . $count . " months"));
                //当月最后一天
                $lastDay = date('Y-m-d', strtotime("$firstDay +1 month -1 day"));
                $newArr[] = [
                    'start_time' => date("Y-m-d 00:00:00", strtotime($firstDay)),
                    'end_time' => date("Y-m-d 23:59:59", strtotime($lastDay)),
                ];
            } else if ('year' == $timeGranularity) {
                $count++;
                $firstDay = date("Y-01-01", strtotime($endTime . "-" . $count . " years"));
                $lastDay = date('Y-m-d', strtotime("$firstDay +1 year -1 day"));
                $newArr[] = [
                    'start_time' => date("Y-01-01 00:00:00", strtotime($firstDay)),
                    'end_time' => date("Y-m-d 23:59:59", strtotime($lastDay)),
                ];
            }
            $num++;
        }
        return $newArr;
    }

    /**
     * Desc: 获取当周星期一的日期
     * @param false $with_second
     * @param false $return_second
     * @return false|int|string
     * Datetime: 2022/12/21 14:56 by zdb
     */
    public static function getCurrentMondayDate($with_second = false, $return_second = false) {
        $w = date("w");
        $diff_day = 0 == $w ? 6 : $w - 1;
        if ($with_second) {
            $date = date("Y-m-d 00:00:00", strtotime("-" . $diff_day . " days"));
        } else {
            $date = date("Y-m-d", strtotime("-" . $diff_day . " days"));
        }
        if ($return_second) {
            return strtotime($date);
        } else {
            return $date;
        }
    }

    /**
     * Notes: 计算月份
     * User: mxj
     * Time: 2023/1/4 10:34
     * @param $numMonth // 月份数量
     * @param $current // 是否包含当前月
     * @return array
     */
    public static function getMonthDate($numMonth = 6, $current = true) {
        $month = array();
        $startDay = date('Y-m');
        if($current){
            array_push($month,date('Y-m'));
            $numMonth -= 1;
        }
        for ($i = 1; $i <= $numMonth; $i++) {
            $dates = date("Y-m", strtotime($startDay. " -" . ($i-1) . " MONTHS -1 DAYS"));
            array_push($month,$dates);
        }
        return array_reverse($month);
    }

    /**
     * Notes:是否为节假日 true 节假日  false 工作日
     * User: mxj
     * Time: 2023/3/6 15:09
     * @param $date  // 格式 2023-05-01
     * @return bool
     * @throws \Exception
     */
    public static function isHoliday ($date) {
        // 节假日情况
        $holiday = HolidayUtil::getHoliday($date);
        if($holiday){
            return true;
        }
        // 周末情况
        $day = Solar::fromDate(new DateTime($date));
        if(in_array($day->getWeek(),[0,6])) {
            return true;
        }
        return false;
    }

    /**
     * 转换时间
     * 默认将天换算成秒
     * @param $val
     * @param string $target
     * @param string $start
     * @param int $bit 小数点精确度位数，默认为1
     * @return float|int
     */
    public static function switchTimeValue($val, $target='second', $start='day', $bit=1){
        $val    = floatval($val);
        $start  = strtolower($start);
        $target = strtolower($target);
        $final_value = 0;
        if('day' == $start){
            //天换算成其它单位
            if( 'second' == $target ){
                $final_value = $val*86400;
            }elseif('minute' == $target){
                $final_value = $val*1440;
            }elseif('hour' == $target){
                $final_value = $val*24;
            }else{
                $final_value = $val;
            }
        }elseif('second' == $start){
            //秒换算成其它单位
            if( 'second' == $target ){
                $final_value = $val;
            }elseif('minute' == $target){
                $final_value = round($val/60,$bit);
            }elseif('hour' == $target){
                $final_value = round($val/3600, $bit);
            }elseif('day' == $target){
                $final_value = round($val/86400, $bit);
            }else{
                $final_value = round($val/(86400*30), $bit);
            }
        }else{

        }
        return $final_value;
    }

    /**
     * 将时间差转为文本形式展示
     * @param $timepoint_diff
     * @param bool $is_short  day有数据，就不显示min; hour有数据，就不显示second
     * @return string
     */
    public static function turnDateDiffToText($timepoint_diff, $is_short = true, $style='default'){
        list($d, $h, $m, $s) = [0, 0, 0, 0];
        $final_text = '';
        $mon = floor($timepoint_diff/(86400*30));
        if($mon){
            $final_text .= $mon.'Months ';
            $timepoint_diff -= $mon*86400*30;
        }
        $d = floor($timepoint_diff/86400);
        if($d){
            $final_text .= 1 == $d ? $d.'Day':$d.'Days';
            $timepoint_diff -= $d*86400;
        }
        $h = floor($timepoint_diff/3600);

        if($is_short){
            if($h){
                if(!$mon){
                    $final_text .= 1 == $h ? $h.'Hour':$h.'Hours';
                }
                $timepoint_diff -= $h*3600;
            }
            $m = floor($timepoint_diff/60);
            if($m){
                if(!$mon && !$d){
                    $final_text .= 1 == $m ? $m.'Mins':$m.'Mins';
                }
                $timepoint_diff -= $m*60;
            }
            if($timepoint_diff){
                if(!$d && !$h){
                    $final_text .= intval($timepoint_diff).'Seconds ';
                }
            }
        }else{
            if($h){
                $final_text .= 1 == $h ? $h.'Hour':$h.'Hours';
                $timepoint_diff -= $h*3600;
            }
            $m = floor($timepoint_diff/60);
            if($m){
                $final_text .= 1 == $m ? $m.'Min':$m.'Mins';
                $timepoint_diff -= $m*60;
            }
            if($timepoint_diff){
                $final_text .= intval($timepoint_diff).'Seconds ';
            }
        }
        if('simple' == $style){
            $final_text = str_replace(['Hours', 'Hour','Mins', 'Min', 'Seconds'], ['h','h','m', 'm','s'], $final_text);
        }
        return $final_text;
    }

    /**
     * Desc: 获取某月所有天数的日期
     * @param $monthDate  "Y-m"格式
     * Datetime: 2023/3/6 17:20 by zdb
     */
    public static function getWholeMonthDay($monthDate)
    {
        $targetArr = [];
        $currentMonth = self::getCurrentDatetime("Y-m");
        $firstDay = $monthDate."-01";
        $nextMonthFirstDay = self::getCustomDatetime($firstDay."+1 month", "Y-m-d");
        for($i=$firstDay; $i<$nextMonthFirstDay;){
            $targetArr[] = $i;
            $i = self::getCustomDatetime($i."+1 day", "Y-m-d");
        }

//        if($monthDate == $currentMonth){
//            $currentDay = self::getCurrentDatetime("Y-m-d");
//            for($i=$firstDay; $i<=$currentDay;){
//                $targetArr[] = $i;
//                $i = self::getCustomDatetime($i."+1 day", "Y-m-d");
//            }
//        }else{
//
//        }
        return $targetArr;
    }

    /**
     * Notes:当天的开始时间戳和结束时间戳
     * User: mxj
     * Time: 2023/4/13 11:20
     * @return array
     */
    public static function currentDayTime () {
        $start_time = strtotime(date("Y-m-d",time()));
        $end_time   = $start_time + 60 * 60 * 24 - 1;
        return ['start_time' => $start_time,'end_time' => $end_time];
    }

    /**
     * 处理月份日期，月份只有一位的时候，补充0
     * @param $monthDate
     * @return string
     */
    public static function dealMonthDate($monthDate)
    {
        $arrDate =explode("-", $monthDate);
        $month = str_pad($arrDate[1], 2, '0',STR_PAD_LEFT);
        return $arrDate[0]."-".$month;
    }

    /**
     * Desc: 获取一个时间区间的时间列表
     * @param $startDate
     * @param $endDate
     * @param string $format
     * @return array
     * Datetime: 2024/11/13 10:24 by zdb
     */
    public static function getPeriodDateList($startDate, $endDate, $format = "Y-m-d")
    {
        $dateArr = [];
        $dateIndex = $startDate;
        for($i=0; $dateIndex<$endDate; $i++){
            $dateIndex = DateUtil::getCustomDatetime($startDate."+".$i." days", $format);
            $dateArr[] = $dateIndex;
        }
        return $dateArr;
    }

    /**
     * 将H:i:s格式时间换算成秒
     * @param $hisFormatTime
     */
    public static function getSecondTimeOfHisFormat($hisFormatTime){
        $hour = intval(date("H", strtotime($hisFormatTime)));
        $minute = intval(date("i", strtotime($hisFormatTime)));
        $second = intval(date("s", strtotime($hisFormatTime)));
        return 3600*$hour + 60*$minute + $second;
    }

}